using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using MediaAssistant.DAL.Constants;

namespace MediaAssistant.DAL.Virtualization
{
    public class LibraryItemProvider : IItemsProvider<LibraryItem>
    {
        private int _count;
        private readonly Dictionary<int, LibraryItem> _startIndexDictionary;
        private readonly IEnumerable<LibraryItem> _rootItems;

        public LibraryItemProvider(IEnumerable<LibraryItem> rootItems)
        {
            _rootItems = rootItems;
            _startIndexDictionary = new Dictionary<int, LibraryItem>();
        }

        private void CalculateCount()
        {
            _count = 0;
            foreach (var rootItem in _rootItems)
            {
                _count++;
                rootItem.Lavel = 0;
                _startIndexDictionary.Add(_count - 1, rootItem);
                GetChildrenCount(rootItem, 0);
            }
        }

        private void GetChildrenCount(LibraryItem item, int label)
        {
            if (!item.IsExpanded)
            {
                return;
            }
            if (LibraryItemType.CanHaveChildren(item.Type) == false)
            {
                return;
            }
            if (LibraryItemType.IsLastParent(item.Type) == false)
            {
                foreach (var child in item.OrderedChildren)
                {
                    _count++;
                    child.Lavel = label + 1;
                    _startIndexDictionary.Add(_count - 1, child);
                    GetChildrenCount(child, label + 1);
                }
            }
            else
            {
                _count += item.Children.Count;
            }
        }

        public int FetchCount()
        {
            lock (DatabaseManager.LockObject)
            {
                CalculateCount();
            }
            return _count;
        }

        public IList<LibraryItem> FetchRange(int startIndex, int count)
        {
            lock (DatabaseManager.LockObject)
            {
                var skippedItems = 0;
                var items = new List<LibraryItem>();
                foreach (var kv in _startIndexDictionary.OrderBy(kv => kv.Key))
                {
                    var endeIndex = kv.Key;
                    if (kv.Value.IsExpanded)
                    {
                        endeIndex += kv.Value.Children.Count;
                    }
                    if (endeIndex < startIndex)
                    {
                        skippedItems = endeIndex + 1;
                        continue;
                    }
                    if (skippedItems < startIndex)
                    {
                        skippedItems++;
                    }
                    else
                    {
                        items.Add(kv.Value);
                        if (items.Count == count)
                            return items;
                    }

                    if (kv.Value.IsExpanded && LibraryItemType.IsLastParent(kv.Value.Type))
                    {
                        foreach (var item in kv.Value.OrderedChildren)
                        {
                            if (skippedItems < startIndex)
                            {
                                skippedItems++;
                            }
                            else
                            {
                                item.Lavel = kv.Value.Lavel + 1;
                                items.Add(item);
                                if (items.Count == count)
                                    return items;
                            }
                        }
                    }
                }
                return items;
            }
        }
    }
}
